package com.bjb.vr.auth.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bjb.vr.auth.bo.UmsUserDetail;
import com.bjb.vr.auth.util.AccessRequestUtil;
import com.bjb.vr.common.ao.*;
import com.bjb.vr.common.constant.*;
import com.bjb.vr.common.dto.*;
import com.bjb.vr.common.mapper.*;
import com.bjb.vr.common.result.BaseResult;
import com.bjb.vr.common.result.CommonResult;
import com.bjb.vr.common.service.SysTenantService;
import com.bjb.vr.common.utils.JwtTokenUtil;
import com.bjb.vr.common.utils.ThreadLocalUtil;
import com.bjb.vr.common.vo.PersonalInfoVo;
import com.bjb.vr.common.vo.UmsAccountVo;
import com.bjb.vr.common.vo.UmsRoleVo;
import io.jsonwebtoken.Claims;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

/**
 * @author admin
 * @description 针对表【ums_account(后台账户表)】的数据库操作Service实现
 * @createDate 2022-03-18 18:00:07
 */
@Service
public class UmsAccountEnhanceService extends ServiceImpl<UmsAccountMapper, UmsAccount> {

    private PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();

    @Resource
    private AuthenticationManager authenticationManager;

    @Resource
    private UmsRoleMapper umsRoleMapper;

    @Resource
    private UmsUserRoleMapper umsUserRoleMapper;

    @Resource
    private ResFavoritesMapper resFavoritesMapper;

    @Resource
    private ResPlaylistMapper resPlaylistMapper;

    @Resource
    private UmsRoleMenuMapper roleMenuMapper;

    @Resource
    private SysTenantService tenantService;

    @Resource
    private UmsAccountMapper umsAccountMapper;

    @Resource
    private UmsOptAccountMapper umsOptAccountMapper;

    /**
     * 更新用户角色
     *
     * @param umsAccountAo
     */
    public boolean updateUserInfo(UmsAccountAo umsAccountAo) {
        UmsAccount umsAccount = new UmsAccount();
        umsAccount.setUserId(umsAccountAo.getUserId());
        // 更新用户角色信息
        if (umsAccountAo.getRoleId() != null) {
            UmsUserRole umsUserRole = new UmsUserRole();
            umsUserRole.setUserId(umsAccountAo.getUserId());
            umsUserRole.setRoleId(umsAccountAo.getRoleId());
            // 判断是否为空:为空新增，否则更新
            UmsUserRole userRole = umsUserRoleMapper.selectOne(new LambdaQueryWrapper<UmsUserRole>().eq(UmsUserRole::getUserId, umsAccountAo.getUserId()));
            if (Objects.isNull(userRole)) {
                umsUserRoleMapper.insert(umsUserRole);
            } else {
                umsUserRoleMapper.update(umsUserRole, new LambdaQueryWrapper<UmsUserRole>().eq(UmsUserRole::getUserId, umsAccountAo.getUserId()));
            }
        }
        // 更新用户信息
        return this.updateById(umsAccount);
    }

    /**
     * 查询角色信息--单条
     *
     * @param roleName
     */
    public UmsRole queryRoleByName(String roleName) {
        UmsRole umsRole = umsRoleMapper.selectOne(new LambdaQueryWrapper<UmsRole>().eq(StringUtils.isNotBlank(roleName), UmsRole::getRoleName, roleName));
        return umsRole;
    }

    /**
     * 查询角色信息--列表
     *
     * @param userRoleAo
     */
    public List<UmsRoleVo> queryRoleInfo(UmsUserRoleAo userRoleAo) {
        List<UmsRoleVo> roleVos = umsRoleMapper.queryRoleInfosByCondition(userRoleAo);
        return roleVos;
    }

    /**
     * 个人中心
     *
     * @return
     */
    public PersonalInfoVo queryPersonalInfo() {
        String username = AccessRequestUtil.getUserName();
        List<PersonalInfoVo> personalInfoVos = umsUserRoleMapper.queryPersonalInfo(username);
        String roleNames = personalInfoVos.stream().map(PersonalInfoVo::getRoleName).collect(Collectors.joining(","));
        PersonalInfoVo personalInfoVo = personalInfoVos.get(0);
        personalInfoVo.setRoleName(roleNames);
        Integer favoriteSize = resFavoritesMapper.queryFavoritesSizeByAccountId(personalInfoVo.getAccountId());
        Integer playListSize = resPlaylistMapper.queryPlayListSizeByAccountId(personalInfoVo.getAccountId());
        String tenantName = tenantService.queryTenantNameByAccountId(personalInfoVo.getAccountId());
        personalInfoVo.setFavoriteSize(favoriteSize);
        personalInfoVo.setPlayListSize(playListSize);
        personalInfoVo.setTenantName(tenantName);
        return personalInfoVo;
    }

    /**
     * 查询当前登录用户的权限
     *
     * @return
     */
    public UmsUserDetail queryAuthorities() {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if (principal instanceof UserDetails) {
            UmsUserDetail umsUserDetail = (UmsUserDetail) principal;
            return umsUserDetail;
        }
        return null;
    }

    /**
     * 新增角色
     *
     * @param umsRoleAo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean addRoleInfo(UmsRoleAo umsRoleAo) {
        AtomicBoolean result = new AtomicBoolean(true);
        // 新增角色
        String username = AccessRequestUtil.getUserName();
        UmsRole umsRole = new UmsRole();
        umsRole.setRoleName(umsRoleAo.getRoleName());
        umsRole.setRemark(umsRoleAo.getRoleName());
        umsRole.setCreateBy(username);
        if (StringUtils.isBlank(umsRoleAo.getRoleKey())) {
            umsRole.setRoleKey(RoleConstants.COMMON);
        }
        umsRoleMapper.insert(umsRole);

        // 关联角色和权限
        Arrays.stream(umsRoleAo.getMenuIds()).forEach(m -> {
            try {
                UmsRoleMenu roleMenu = new UmsRoleMenu();
                roleMenu.setRoleId(umsRole.getRoleId());
                roleMenu.setMenuId(m);
                roleMenu.setType(umsRoleAo.getType());
                roleMenuMapper.insert(roleMenu);
            } catch (Exception e) {
                result.set(false);
                log.error(e.getMessage());
            }
        });
        return result.get();
    }

    /**
     * 编辑角色
     *
     * @param umsRoleAo
     * @return
     */
    public boolean updateRole(UmsRoleAo umsRoleAo) {
        AtomicBoolean result = new AtomicBoolean(true);
        // 修改角色
        String username = AccessRequestUtil.getUserName();
        UmsRole umsRole = new UmsRole();
        umsRole.setId(umsRoleAo.getId());
        umsRole.setRoleName(umsRoleAo.getRoleName());
        umsRole.setRemark(umsRoleAo.getRoleName());
        umsRole.setStatus(umsRoleAo.getStatus());
        umsRole.setUpdateBy(username);
        umsRoleMapper.updateById(umsRole);

        if (Objects.isNull(umsRoleAo.getMenuIds())) {
            result.set(true);
            return result.get();
        }

        LambdaQueryWrapper<UmsRoleMenu> deleteWrapper = new LambdaQueryWrapper<>();
        deleteWrapper.eq(UmsRoleMenu::getRoleId, umsRoleAo.getRoleId());
        roleMenuMapper.delete(deleteWrapper);
        // 关联角色和权限
        Arrays.stream(umsRoleAo.getMenuIds()).forEach(m -> {
            try {
                UmsRoleMenu roleMenu = new UmsRoleMenu();
                roleMenu.setRoleId(umsRoleAo.getRoleId());
                roleMenu.setMenuId(m);
                roleMenu.setType(umsRoleAo.getType());
                roleMenuMapper.insert(roleMenu);
            } catch (Exception e) {
                result.set(false);
                log.error(e.getMessage());
            }
        });
        return result.get();
    }

    /**
     * 更新用户密码
     *
     * @param accountPwdAo
     * @return
     */
    public boolean updateUserPassword(UmsAccountPwdAo accountPwdAo) {
        // 认证用户名密码
        UmsAccountVo umsAccountVo = (UmsAccountVo) ThreadLocalUtil.get(ThreadLocalConstant.USER_ACCOUNT_INFO);
        try{
            String loginType = accountPwdAo.getLoginType();
            if (LoginConstant.MANAGER.equals(loginType)) {
                UmsAccount umsAccount = new UmsAccount();
                umsAccount.setId(umsAccountVo.getId());
                umsAccount.setInitialPass(Constants.NO);
                if (StringUtils.isNotBlank(accountPwdAo.getPassword())) {
                    umsAccount.setPassword(passwordEncoder.encode(accountPwdAo.getPassword()));
                }
                return umsAccountMapper.updateById(umsAccount) == 1;
            }else {
                UmsOptAccount umsOptAccount = new UmsOptAccount();
                umsOptAccount.setId(umsAccountVo.getId());
                umsOptAccount.setInitialPass(Constants.NO);
                if (StringUtils.isNotBlank(accountPwdAo.getPassword())) {
                    umsOptAccount.setPassword(passwordEncoder.encode(accountPwdAo.getPassword()));
                }
                return umsOptAccountMapper.updateById(umsOptAccount) == 1;
            }
        }catch (Exception e){
            log.error(e.getMessage());
            return false;
        }
    }

    /**
     * 更新客户密码
     *
     * @param accountPwdAo
     * @return
     */
    public boolean updateCustomerPassword(UmsAccountPwdAo accountPwdAo) {
        try{
            // 认证用户名密码
            UmsAccountVo umsAccountVo = (UmsAccountVo) ThreadLocalUtil.get(ThreadLocalConstant.USER_ACCOUNT_INFO);
            UmsAccount umsAccount = new UmsAccount();
            umsAccount.setId(umsAccountVo.getId());
            umsAccount.setInitialPass(Constants.NO);
            if (StringUtils.isNotBlank(accountPwdAo.getPassword())) {
                umsAccount.setPassword(passwordEncoder.encode(accountPwdAo.getPassword()));
            }
            // 更新用户密码
            return this.updateById(umsAccount);
        }catch (Exception e){
            log.error(e.getMessage());
            return false;
        }
    }

    /**
     * 更新用户状态
     *
     * @param statusAo
     * @return
     */
    public boolean updateUserStatus(UmsAccountStatusAo statusAo) {
        UmsAccount umsAccount = new UmsAccount();
        umsAccount.setId(statusAo.getId());
        umsAccount.setStatus(statusAo.getStatus());
        // 更新用户密码
        return this.updateById(umsAccount);
    }

    /**
     * 判断是否为超级管理员
     *
     * @param userId
     * @param userName
     * @return
     */
    public boolean checkSuperAdmin(Long userId, String userName) {
        LambdaQueryWrapper<UmsAccount> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Objects.nonNull(userId), UmsAccount::getUserId, userId);
        queryWrapper.eq(StringUtils.isNotBlank(userName), UmsAccount::getUsername, userName);
        UmsAccount umsAccount = this.getOne(queryWrapper);
        if (Objects.isNull(umsAccount)) {
            return false;
        }
        if (umsAccount.getSuperMan().equals(RoleConstants.SUPER_IDENTIFY)) {
            return true;
        }
        return false;
    }

    /**
     * 校验用户名密码是否正确
     *
     * @param authorization
     * @param accountResetPwdAo
     * @return
     */
    public BaseResult verifyUserNameAndPassword(String authorization, UmsAccountResetPwdAo accountResetPwdAo) {
        // 认证用户名密码
        Claims claims = JwtTokenUtil.parseJWT(authorization);
        String username = String.valueOf(claims.get(TokenConstants.TOKEN_USERNAME));
        String loginType = String.valueOf(claims.get(TokenConstants.LOGIN_TYPE));
        try {
            Authentication authenticate = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, accountResetPwdAo.getOldPassword()));
            boolean authenticated = authenticate.isAuthenticated();
            if (authenticated) {
                UmsUserDetail principal = (UmsUserDetail) authenticate.getPrincipal();
                UmsAccountPwdAo umsAccountPwdAo = new UmsAccountPwdAo();
                umsAccountPwdAo.setId(principal.getUserId());
                umsAccountPwdAo.setPassword(accountResetPwdAo.getNewPassword());
                umsAccountPwdAo.setLoginType(loginType);
                return CommonResult.Ok().setResult(umsAccountPwdAo);
            }
            return CommonResult.Fail("旧密码错误,认证失败！");
        } catch (Exception e) {
            return CommonResult.Fail("旧密码错误,认证失败！");
        }
    }

}




